package org.kjk.oracleDB;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Vector;

public class ConnectionPool {
	private static ConnectionPool cp = null;
	
	private ConnectionFactory cf = null;
	private Vector<Connection> pool = null;
	@SuppressWarnings("unused")
	private int initCon = 0;
	private int maxCon = 0;
	private int users = 0;
	
	private ConnectionPool(int initCon, int maxCon) {
		this.initCon = initCon;
		this.maxCon = maxCon;
		cf = new ConnectionFactory();
		pool = new Vector<Connection>();
		
		for (int i = 0; i < initCon; i++) {
			pool.add(createConnection());
		}
	}
	
	public static synchronized ConnectionPool getInstance() throws SQLException {
		if (cp == null) {
			cp = new ConnectionPool(4, 20);
		}
		return cp;
	}
	
	public synchronized Connection getConnection() throws SQLException {
		Connection conn = null;
		while ((conn = getPooledConnection()) == null) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		users++;
		return conn;
	}
	
	private Connection getPooledConnection() {
		Connection conn = null;
		int size = pool.size();
		if (size > 0) {
			conn = (Connection) pool.elementAt(0);
			pool.removeElementAt(0);
		} else if (users < maxCon || maxCon == 0) {
			pool.add(createConnection());
		}
		return conn;
	}

	private Connection createConnection() {
		Connection conn = cf.getConnection(ConnectionFactory.ORACLE);
		return conn;
	}
	
	public void close(ResultSet rs, Statement stmt, Connection conn) {
		try {
			if (rs != null) {
				rs.close();
			}
			if (stmt != null) {
				stmt.close();
			}
			if (conn != null) {
				releaseConnection(conn);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	public synchronized void releaseConnection(Connection conn) {
		pool.add(conn);
		users--;
		notifyAll();
	}
	
}
